package com.zhida.jiyangcenter.utils

import android.content.Context
import android.content.SharedPreferences
import chooongg.base.manager.app
import java.lang.reflect.ParameterizedType

open class SPKey<T>(val key: String, val default: T, val spName: String = SPUtils.DEFAULT_SP_NAME) {
    fun getTClass() = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<*>
    fun get(default: T = this.default) = SPUtils.init(spName).get(this, default)
    fun put(value: T?) {
        SPUtils.init(spName).put(this, value)
    }
}

object SPUtils {

    const val DEFAULT_SP_NAME = "default"

    fun init(spName: String = DEFAULT_SP_NAME) = SPManager(app.getSharedPreferences(spName, Context.MODE_PRIVATE))

    class SPManager(val sp: SharedPreferences) {
        fun <T> put(spKey: SPKey<T>, value: T?) = apply {
            val editor = sp.edit()
            if (value == null) {
                editor.remove(spKey.key)
            } else {
                when (spKey.getTClass()) {
                    Int::class.javaObjectType -> editor.putInt(spKey.key, value as Int)
                    Long::class.javaObjectType -> editor.putLong(spKey.key, value as Long)
                    Float::class.javaObjectType -> editor.putFloat(spKey.key, value as Float)
                    Double::class.javaObjectType -> editor.putString(spKey.key, value.toString())
                    String::class.javaObjectType -> editor.putString(spKey.key, value as String)
                    Boolean::class.javaObjectType -> editor.putBoolean(spKey.key, value as Boolean)
                    else -> throw ClassCastException("SP中不支持此类型")
                }
            }
            editor.apply()
        }

        @Suppress("UNCHECKED_CAST", "RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
        fun <T> get(spKey: SPKey<T>, default: T): T {
            return if (sp.contains(spKey.key)) {
                return when (spKey.getTClass()) {
                    Int::class.javaObjectType -> sp.getInt(spKey.key, default as Int? ?: 0) as T
                    Long::class.javaObjectType -> sp.getLong(spKey.key, default as Long? ?: 0) as T
                    Float::class.javaObjectType -> sp.getFloat(spKey.key, default as Float?
                            ?: 0f) as T
                    Double::class.javaObjectType -> (sp.getString(spKey.key, (default as Double?)?.toString()
                            ?: "0.0")!!.toDoubleOrNull()) as T
                    String::class.javaObjectType -> sp.getString(spKey.key, default as String?
                            ?: "") as T
                    Boolean::class.javaObjectType -> sp.getBoolean(spKey.key, default as Boolean?
                            ?: false) as T
                    else -> throw ClassCastException("SP中不支持此类型")
                }
            } else {
                default
            }
        }

        fun remove(vararg spKey: SPKey<*>) = apply {
            if (spKey.isNotEmpty()) {
                val editor = sp.edit()
                for (item in spKey) {
                    editor.remove(item.key)
                }
                editor.apply()
            }
        }

        fun clear() = sp.edit().clear().apply()
    }
}